from tortoise.expressions import F, RawSQL
from typing import List
import random

from models.song import Song
from models.song_favorite import SongFavorite
from models.song_sheet import SongSheet
from util.log import Log
from util.redis import Redis
from util.array import Array
from util.time import Time
from util.token import MusicToken
from common.const import BaseConstant

async def getSongByMD5(md5: str):
    try:
        song = await Song.filter(md5=md5).first()
        return song
    except Exception as e:
        raise e

async def getSongById(songId: int):
    try:
        song = await Song.filter(id=songId).first()
        return song
    except Exception as e:
        raise e

async def createSong(song: dict):
    try:
        res = await Song.create(**song)
        return res
    except Exception as e:
        raise e

'''
Redis
通过 userId 获取 song 的搜索历史
'''
async def getSearchHistoryByUserId(userId: int):
    try:
        key = BaseConstant.SONG_SEARCH_HISTORY_KEY % userId
        history = Redis.getItem(key)
        if history == None:
            return []
        else:
            return history.get("history")
    except Exception as e:
        raise e
    
'''
Redis
更新 userId 的搜索历史
'''
async def updateSearchHistoryByUserId(keyword, userId):
    try:
        key = BaseConstant.SONG_SEARCH_HISTORY_KEY % userId

        historyList = await getSearchHistoryByUserId(userId)
        
        if keyword in historyList:
            historyList.remove(keyword)
        else:
            while len(historyList) >= 10:
                historyList.pop()
        historyList.insert(0, keyword)

        Redis.setItem(key, {
            "history": historyList
        }, 60 * 60 * 24 * 7)
    except Exception as e:
        raise e


'''
根据 type 来查询 song 列表，有 name、singer
'''
async def getSongListByType(keyword, type):
    try:
        res = []
        if type == 'name':
            res = await Song.filter(name__icontains=keyword).all()
        elif type == 'singer':
            res = await Song.filter(singer__icontains=keyword).all()
        return res
    except Exception as e:
        raise e

'''
获取每日推荐歌曲
'''
async def getDailyRecommendSongList() -> List[Song]:
    try:
        res = []
        key = BaseConstant.SONG_DAILY_RECOMMEND_KEY
        recommendObj = Redis.getItem(key)

        if recommendObj == None:
            # 未生成
            songList = await Song.filter().all()
            randomList = Array.randomNumberList(30, 0, len(songList) - 1, True)
            # Log.debug('randomList', randomList)
            for item in randomList:
                res.append(dict(songList[item]))

            # Log.debug('Time.getTimeToNextDay()', Time.getTimeToNextDay())

            Redis.setItem(key, {
                "songList": res
            }, Time.getTimeToNextDay())
        else:
            res = recommendObj.get("songList")
        return res
    except Exception as e:
        raise e

'''
获取歌曲密钥
'''
async def getSecretKey(userId, songId):
    try:
        secretKey = ''
        key = BaseConstant.MUSIC_SECRET_KEY % ('%s-%s' % (userId, songId))
        
        token = Redis.getItem(key)
        if token == None:
            secretKey = MusicToken().generateToken({
                'userId': userId,
                'songId': songId
            })
            Redis.setItem(key, {
                'key': secretKey
            }, 60 * 60)
        else:
            secretKey = token.get("key")

        return secretKey
    except Exception as e:
        raise e


'''
获取用户收藏状态列表
'''
async def getSongFavoriteList(songIdList: list, userId: int):
    try:
        songFavorite = await SongFavorite.filter(song_id__in=songIdList, user_id=userId, sheet_id=0).all()
        return songFavorite
    except Exception as e:
        raise e


''''
更新用户收藏歌曲状态
'''
async def updateSongFavorite(favorite: dict):
    try:
        songId = favorite.get("songId")
        userId = favorite.get("userId")
        sheetId = favorite.get("sheetId")
        songFavorite = await SongFavorite.filter(song_id=songId, user_id=userId, sheet_id=sheetId).first()
        if songFavorite == None:
            res = await SongFavorite.create(
                song_id=songId,
                user_id=userId,
                sheet_id=sheetId
            )
        else:
            if sheetId == 0:
                res = await SongFavorite.filter(song_id=songId, user_id=userId, sheet_id=sheetId).delete()
            else:
                return 1
        return res
    except Exception as e:
        raise e


'''
获取我喜欢的歌曲列表
'''
async def getILikeSongList(userId: int):
    try:
        favoriteList = await SongFavorite.filter(user_id=userId, sheet_id=0).all()
        idList = [item.song_id for item in favoriteList]
        songList = await Song.filter(id__in=idList).all()
        return songList
    except Exception as e:
        raise e

'''
通过 sheet 的 id list，获取收藏记录
'''
async def getFavoriteListBySheetIdList(sheetIdList: list):
    try:
        favoriteList = await SongFavorite.filter(sheet_id__in=sheetIdList).all()
        return favoriteList
    except Exception as e:
        raise e

async def getFavoriteListBySheetId(sheetId: str):
    try:
        favoriteList = await SongFavorite.filter(sheet_id=sheetId).all()
        return favoriteList
    except Exception as e:
        raise e 

'''
创建歌单
'''
async def createSongSheet(songSheet: dict):
    try:
        res = await SongSheet.create(**songSheet)
        return res
    except Exception as e:
        raise e

'''
获取用户自己创建的歌单列表
'''
async def getSheetListByUserId(userId: int):
    try:
        res = await SongSheet.filter(user_id=userId).all()
        return res
    except Exception as e:
        raise e

'''
通过 id 获取歌单
'''
async def getSheetById(sheetId: str):
    try:
        res = await SongSheet.filter(id=sheetId).first()
        return res
    except Exception as e:
        raise e

'''
更新歌单
'''
async def updateSongSheet(sheetId: str, sheet: dict):
    try:
        res = await SongSheet.filter(id=sheetId).update(**sheet)
        return res
    except Exception as e:
        raise e  


'''
通过 id list 获取 song list
'''
async def getSongListByIdList(songIdList: list):
    try:
        res = await Song.filter(id__in=songIdList).all()
        return res
    except Exception as e:
        raise e  
    
'''
获取 推荐的 歌单
'''
async def getRecommendSheetList(length: int):
    try:
        sheetList = await SongSheet.all()
        
        # sample 获取不同元素，chioce 获取可重复元素
        res = random.sample(sheetList, int(min(length, len(sheetList))))

        return res
    except Exception as e:
        raise e    


